import {MicroAppModule} from "./MicroAppModule";
import {computed, delay, designComponent, onBeforeUnmount, onMounted, PropType, reactive, RenderNode} from "@peryl/react-compose";
import {createEffects} from "@peryl/utils/createEffects";
import {$loading, Loading} from "plain-design";
import {iMicroAppPageConfig, iMicroConfig, iMicroMainRenderModeBase, iMicroPageMeta, iMicroPageServiceProvideData, isPathMatchMicroConfig} from "@peryl/micro-web";
import {MicroAppPageRender} from "./MicroApp.pageRender";
import {MicroAppPageButton} from "./MicroApp.pageButton";
import {MicroAppPageConfig} from "./MicroApp.pageConfig";
import {MicroAppPageNavigation} from "./MicroApp.pageNavigation";

export const microAppPageList = MicroAppModule.createRegistration((microApp) => {

  const { effects: pageLoadingEffects } = createEffects();
  const loadedMap = {} as Record<string, boolean | undefined>;

  /**
   * 子应用用这个组件来渲染子应用所需要展示的页面
   * @author  韦胜健
   * @date    2024/1/31 17:56
   */
  return designComponent({
    props: {
      microConfig: { type: undefined as any as PropType<iMicroConfig>, required: true },
      getPageComponent: { type: undefined as any as PropType<iMicroMainRenderModeBase['getPageComponent']>, required: true }
    },
    setup({ props }) {
      const { microConfig, getPageComponent } = props;
      const { effects: setupEffects } = createEffects();
      const getPages = () => {
        return microApp.state.tabs.reduce((prev, item) => {
          item.pages.forEach(page => {isPathMatchMicroConfig(page.path, microConfig) && prev.push(page);});
          return prev;
        }, [] as iMicroPageMeta[]);
      };
      const state = reactive({ pages: getPages(), });
      setupEffects.push(microApp.hooks.onPagesChange.use(() => {state.pages = getPages();}));
      onBeforeUnmount(setupEffects.clear);

      const Page = designComponent({
        props: {
          pageMeta: { type: undefined as any as PropType<iMicroPageMeta>, required: true },
        },
        setup({ props }) {

          const nav = microApp.createPageNav(props.pageMeta);
          // const closeLoading = nav.loading();
          const tabMeta = microApp.state.tabs.find(tab => tab.pages.find(p => p.id == props.pageMeta.id));

          if (!tabMeta) {return () => null;}

          const isFirstPage = tabMeta.pages[0].id == props.pageMeta.id;

          /*异步加载页面组件的渲染函数*/
          const state = reactive({ render: null as null | (() => RenderNode) });
          /*页面按钮*/
          const pageButton = MicroAppPageButton.useProvider();
          /*页面配置*/
          const pageConfig: iMicroAppPageConfig = (() => {
            const _pageConfig = MicroAppPageConfig.useProvider(pageButton, isFirstPage);
            return reactive({
              title: computed(() => _pageConfig.pageConfig.value.title),
              hideNavigation: computed(() => _pageConfig.pageConfig.value.hideNavigation),
              showBackButton: computed(() => _pageConfig.pageConfig.value.showBackButton),
              buttons: computed(() => _pageConfig.pageConfig.value.buttons),
            });
          })();
          const onBack = (listener: (backData?: any) => void) => {
            const { effects: backEffects } = createEffects();
            const dispose = backEffects.clear;
            onBeforeUnmount(dispose);

            backEffects.push(
              microApp.hooks.onHandleBackData.use(({ handlePageMeta, backData }) => {
                if (handlePageMeta.id === props.pageMeta.id && handlePageMeta.path === props.pageMeta.path) {
                  listener(backData);
                }
              })
            );

            return dispose;
          };

          const pageServiceProvideData: iMicroPageServiceProvideData = {
            microApp,
            nav,
            pageMeta: props.pageMeta,
            pageParam: props.pageMeta.data,
            tabMeta,
            isFirstPage,
            pageConfig,
            onBack,
          };
          microApp.usePageServiceProvider(pageServiceProvideData);

          const pageRender = MicroAppPageRender.useProvider(pageServiceProvideData);
          MicroAppPageNavigation.useProvider(pageServiceProvideData, pageRender);
          onBeforeUnmount(pageRender.hooks.onPageRender.use({ processor: ({ list, render }) => {list.push({ render, seq: 1, key: 'default' });}, render: () => <>{state.render?.()}</> }));

          onMounted(async () => {
            /*这里加点延迟，不然页面初始化快了的话，micro-page-list-item节点高度渲染不及时导致自动高度计算不准确*/
            await delay(23);
            try {
              !loadedMap[props.pageMeta.path] && pageLoadingEffects.push($loading());
              const Component = await getPageComponent({ page: props.pageMeta, microApp, microConfig });
              loadedMap[props.pageMeta.path] = true;
              state.render = () => <Component/>;
            } catch (e) {
              console.error(e);
              state.render = () => <div>{`无法识别页面:${props.pageMeta.path}`}</div>;
            } finally {
              // closeLoading();
              delay(78).then(() => pageLoadingEffects.clear());
            }
          });

          const styles = { height: '100%', width: '100%' };

          return () => (
            <div className="micro-page-list-item" style={styles} data-active={String(props.pageMeta.show)}>
              {nav.loading.isLoading() && <div className="micro-page-loading"><Loading/></div>}
              {pageRender.render()}
            </div>
          );
        },
      });

      const styles = { height: '100%', width: '100%' };

      return () => (
        <div className="micro-page-list" style={styles}>
          {state.pages.map((item) => <Page key={item.id} pageMeta={item}/>)}
        </div>
      );
    },
  });
});
